package com.travel.modules.sys.controller;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.UploadFileRequest;
import com.travel.commons.utils.R;
import com.travel.config.AliOSSConfig;
import com.travel.modules.sys.service.AliOSSService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/oss")
public class AliOSSUploader {
    @Resource
    private AliOSSConfig aliOSSConfig;

    @Resource
    private AliOSSService aliOSSService;

    /**
     * 上传
     * @param file file - 文件
     */
    @RequestMapping("/upload")
    public R upload(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.root(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    @RequestMapping("/upload/scenic")
    public R scenic(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.scenic(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    @RequestMapping("/upload/hotel")
    public R hotel(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.hotel(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    @RequestMapping("/upload/route")
    public R route(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.route(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    @RequestMapping("/upload/advertise")
    public R advertise(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.advertise(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    @RequestMapping("/upload/avatar")
    public R avatar(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.avatar(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    @RequestMapping("/upload/strategy")
    public R strategy(@RequestParam(value = "file") MultipartFile file) {
        if (file == null) {
            return R.error("缺少存储对象");
        }

        String fileName = UUID.randomUUID().toString().replace("-", "") + file.getOriginalFilename();
        String url = null;
        try (
                InputStream is = file.getInputStream()
                ) {
            url = aliOSSService.strategy(fileName, is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok().put("url", url);
    }

    /**
     * 获取url
     * @param param folder - 文件夹路径
     *              name - 文件名
     */
    @RequestMapping("/url")
    public R url(@RequestBody Map<String, String> param) {
        String folder = param.get("folder");
        String name = param.get("name");
        if (StringUtils.isBlank(folder) || StringUtils.isBlank(name)) {
            return R.error("缺少参数");
        }

        String orgUrl;
        OSS ossClient = new OSSClient(aliOSSConfig.getEndPoint(), aliOSSConfig.getAccessKeyId(), aliOSSConfig.getAccessKeySecret());
        try {
            ossClient.getObject(aliOSSConfig.getBucketName(), folder + "/" + name);
            Date expire = new Date(new Date().getTime() + (1000L * 60 * 60 * 24 * 365 * 100));
            orgUrl = ossClient.generatePresignedUrl(aliOSSConfig.getBucketName(), folder + "/" + name, expire).toString();
        } catch (OSSException ossEx) {
            log.error(ossEx.getMessage());
            orgUrl = "获取文件失败";
        } catch (ClientException clientEx) {
            log.error(clientEx.getMessage());
            orgUrl = "OSS服务器异常";
        }
        ossClient.shutdown();

        try {
            folder = URLEncoder.encode(folder, "utf-8");
            name = URLEncoder.encode(name, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
        String url = "https://" + aliOSSConfig.getBucketName() + "." + aliOSSConfig.getEndPoint() + "/" + folder + "/" + name;
        return R.ok().put("normal-url", url)
                     .put("expire-url", orgUrl);
    }

    /**
     * 删除
     * @param param url
     */
    @RequestMapping("/del")
    public R del(@RequestBody Map<String, Object> param) {
        String url = (String) param.get("url");
        if (url == null) {
            return R.error("缺少参数");
        }
        String folderName = url.split(aliOSSConfig.getBucketName() + "." + aliOSSConfig.getEndPoint() + "/")[1];
        String folder;
        String fileName;
        try {
            folder = URLDecoder.decode(folderName.split("/")[0], "utf-8");
            try {
                fileName = URLDecoder.decode(folderName.split("/")[1], "utf-8");
            } catch (ArrayIndexOutOfBoundsException e) {
                fileName = folder;
                folder = "";
            }
        } catch (UnsupportedEncodingException | NullPointerException e) {
            e.printStackTrace();
            return R.error("转码失败");
        }

        String key = StringUtils.isBlank(folder) ? fileName : folder + "/" + fileName;
        OSS ossClient = new OSSClient(aliOSSConfig.getEndPoint(),aliOSSConfig.getAccessKeyId(), aliOSSConfig.getAccessKeySecret());
        ossClient.deleteObject(aliOSSConfig.getBucketName(), key);
        ossClient.shutdown();
        return R.ok();
    }
}
